/******************************************************************
  Copyright (C), 2011-2014, SumaVision S&T Co. Ltd.
  File name: udpTest.c
  Author:    xueyulong
  Version:  1.0
  Date: 2011-09-22
  Description: test the udp communication
  Others: NULL
******************************************************************/

#include   "vxWorks.h"   
#include   "sockLib.h"   
#include   "inetLib.h"   
#include   "stdioLib.h"   
#include   "strLib.h"   
#include   "ioLib.h"   
#include   "fioLib.h"  
#include   "hostLib.h"
#include   "taskLib.h"   

#define   SERVER_PORT_NUM                  5002         /* server's port number for bind() */   
#define   REQUEST_MSG_SIZE                 1024         /* max size of request message */   
  
/* structure used for client's request */ 
struct request   
{
	int display;				/* TRUE = display message */   
        char message[REQUEST_MSG_SIZE];           /* message buffer */   
}; 


/* udpClient.c - UDP client example */   
  
/*   
DESCRIPTION   
This file contains the client-side of the VxWorks UDP example code.   
The example code demonstrates the useage of several BSD 4.4-style   
socket routine calls.   
*/      
  
/*******************************************************************************************************************
*   
*   udpClient - send a message to a server over a UDP socket   
*   
*   This routine sends a user-provided message to a server over a UDP socket.   
*   Optionally, this routine can request that the server display the message.   
*   This routine may be invoked as follows:   
*               ->udpClient "remoteSystem"   
*               Message to send:   
*               Greetings from UDP client   
*               Would you like server to display your message (Y or N):     
*               y   
*               value = 0 = 0x0   
*   
*   RETURNS: OK, or ERROR if the message could not be sent to the server.   
********************************************************************************************************************/ 
STATUS	udpClient
	(
		char * serverName           /* name or IP address of server */
	)
{   
        struct request  myRequest;           /* request to send to server */   
        struct sockaddr_in  serverAddr;         /* server's socket address */   
        char   display;               /* if TRUE, server prints message */   
        int    sockAddrSize;     /* size of socket address structure */   
        int    sFd;              /* socket file descriptor */     
        int    mlen;             /* length of message */     
  
        /* create client's socket */   
  
        if ((sFd = socket (AF_INET, SOCK_DGRAM, 0)) == ERROR)   
        {       
		perror ( "socket" );   
                return ( ERROR );   
        }   
  
        /* bind not required - port number is dynamic */   
  
        /* build server socket address */   
  
        sockAddrSize = sizeof (struct sockaddr_in);   
        bzero ((char *) &serverAddr, sockAddrSize);   
        serverAddr.sin_len = (u_char) sockAddrSize;   
        serverAddr.sin_family = AF_INET;   
        serverAddr.sin_port = htons (SERVER_PORT_NUM);   
  
        if   (((serverAddr.sin_addr.s_addr = inet_addr (serverName)) == ERROR) && 
                ((serverAddr.sin_addr.s_addr = hostGetByName (serverName)) == ERROR))   
        {   
                perror ( "unknown server name ");   
                close (sFd);   
                return (ERROR);   
        }   
  
        /* build request, prompting user for message */   
  
        printf ( "Message to send: \n ");   
        mlen = read (STD_IN, myRequest.message, REQUEST_MSG_SIZE);   
        myRequest.message[mlen - 1] = '\0';   
  
        printf ( "\r\nWould you like the server to display your message (Y or N):");   
        read (STD_IN, &display, 1);   
        switch (display)   
        {   
                case 'y':   
                case 'Y':
			myRequest.display = TRUE;   
                        break;   
                default:
			myRequest.display = FALSE;   
                        break;   
        }   
  
        /* send request to server */   
  
        if (sendto (sFd, (caddr_t) &myRequest, sizeof (myRequest), 0, 
                (struct sockaddr *) &serverAddr, sockAddrSize) == ERROR)   
        {   
                perror ( "sendto ");   
                close (sFd);   
                return (ERROR);   
        }   
  
        close (sFd);   
        return (OK);   
} 


/* udpServer.c - UDP server example */   
  
/*   
DESCRIPTION   
This file contains the server-side of the VxWorks UDP example code.   
The example code demonstrates the useage of several BSD 4.4-style   
socket routine calls.   
*/
  
/******************************************************************************************************
*   
*   udpServer - read from UDP socket and display client's message if requested     
*   
*   Example of VxWorks UDP server:   
*               -> sp udpServer   
*               task spawned: id = 0x3a1f6c, name = t2   
*               value = 3809132 = 0x3a1f6c  
*               -> MESSAGE FROM CLIENT (Internet Address 150.12.0.11, port 1028):   
*               Greetings from UDP client   
*   
*   RETURNS: Never, or ERROR if a resources could not be allocated.   
*******************************************************************************************************/   
  
STATUS   udpServer   (void)   
{   
        struct   sockaddr_in     serverAddr;         /* server's socket address */   
        struct   sockaddr_in     clientAddr;         /* client's socket address */   
        struct   request         clientRequest;   /* request/Message from client */   
        int      sockAddrSize;     /* size of socket address structure */   
        int      sFd;                       /* socket file descriptor */   
        char     inetAddr[INET_ADDR_LEN];   
        /* buffer for client's inet addr */   
  
        /* set up the local address */   
  
        sockAddrSize = sizeof (struct sockaddr_in);   
        bzero ((char *) &serverAddr, sockAddrSize);   
        serverAddr.sin_len = (u_char) sockAddrSize;   
        serverAddr.sin_family = AF_INET;   
        serverAddr.sin_port = htons (SERVER_PORT_NUM);   
        serverAddr.sin_addr.s_addr = htonl (INADDR_ANY);   
  
        /* create a UDP-based socket */   
  
        if ((sFd = socket (AF_INET, SOCK_DGRAM, 0)) == ERROR)   
        {   
                perror ( "socket ");   
                return (ERROR);   
        }   
  
        /* bind socket to local address */   
  
        if (bind (sFd, (struct sockaddr *) &serverAddr, sockAddrSize) == ERROR)   
        {   
                perror ( "bind");   
                close (sFd);   
                return (ERROR);
	}   
  
        /* read data from a socket and satisfy requests */   
  
        FOREVER   
        {   
                if (recvfrom (sFd, (char *) &clientRequest, sizeof (clientRequest), 0, 
                        (struct sockaddr *) &clientAddr, &sockAddrSize) == ERROR)   
                {   
                        perror ( "recvfrom ");   
                        close (sFd);   
                        return (ERROR);   
                }   
  
                /* if client requested that message be displayed, print it */   
  
                if (clientRequest.display)   
                {   
                        /* convert inet address to dot notation */   
  
                        inet_ntoa_b (clientAddr.sin_addr, inetAddr);   
                        printf ( "MSG FROM CLIENT (Internet Address %s, port %d):\n%s\n ",
                                 inetAddr, ntohs (clientAddr.sin_port), clientRequest.message);   
                }   
        }   
}

void udpTest(void)
{
	taskSpawn("tUdpServer",100,VX_NO_STACK_FILL,2000,(FUNCPTR)udpServer,0,0,0,0,0,0,0,0,0,0);
	udpClient("127.0.0.1");
}